package edu.cmsc611.textsimulator;
import java.util.*;
import java.lang.*;

/**
 * Fetch handles the fetch stage of execution.
 */
class Fetch extends Stage {
	/**
	 * the number of instructions in the program.
	 */
	private int instructionSize;
	OutputChart tablechart=null;
	private int savePC;
    LRUCache cache;//=LRUCache.getInstance();
	/**
	 * creates a Fetch object and initializes its fields.
	 * This will create while it first start execution and later
	 * from step, next instruction will be loaded
	 */
	public Fetch() {
		super();
		PC = -1;  // set program counter so first instruction is PC=0
		instructionSize = 0;
	}

	/**
	 * process the current instruction.  Implements the fetch stage of a pipeline.
	 * Uses an instruction vector as well as the Decode stage.
	 * @see Instruction
	 * @see Decode
	 */
	public void step(Vector Instructions, Decode myDecode,Stages stg) {
		instructionSize = Instructions.size();
		cache=LRUCache.getInstance();
		int tempPC=PC;
		// if no stall at decode, move PC to next instruction

		if (myDecode.isStall == false) {
			if ((PC < Instructions.size()) && (Instructions.size()>0) )
				//PC++;
				tempPC++;
			// load next instruction; if no more instructions, issue NOP

			/*
			 * check if need it hit to cache memory
			 */
			ICacheManager icache=ICacheManager.getInstance();
			Instruction tempinst=null;
			if(tempPC < Instructions.size()){
				tempinst=(Instruction) Instructions.elementAt(tempPC);

				if(icache.search(tempPC, tempinst.instructionString, tempinst.getInstruction_index(), Instructions))
				{
					PC++;
					cache.setInsRequested(cache.getInsRequested()+1);

					if ((PC >= 0) && (PC < Instructions.size()) ){
						myInstruction = (Instruction) Instructions.elementAt(PC);
						/*
						 * Insert instruction to charts first column
						 */

						
						Utilities utils=Utilities.getInstance();
						
						/*
						 * update the iteration number while it get access
						 */
						myInstruction.setIteration_index(utils.getLoopiteration());
						
						int iteration=myInstruction.getIteration_index()*Instructions.size();
						tablechart=OutputChart.getInstance();
						tablechart.setvalue(myInstruction.getInstruction_index()+iteration+1, 0, myInstruction.instructionString);


						if(!myInstruction.instructionString.equals("NOP"))
						{
							tablechart.setvalue(myInstruction.getInstruction_index()+iteration+1, 1, Integer.toString(stg.nCycles));
							//System.out.println("instruction="+myInstruction.getInstruction_index()+": Fetch at ="+stg.nCycles);
							
							if(myInstruction.opcode==82){
							//Utilities utils=Utilities.getInstance();
							//OutputChart tablechart=OutputChart.getInstance();
							//iteration=utils.getLoopiteration()*Instructions.size();
							//tablechart.setvalue(funit.getIntUnit2().peek().instruction_index+iteration+1, 8, "Y");
							tablechart.setvalue(myInstruction.instruction_index+iteration+1, 8, "");
							tablechart.setvalue(myInstruction.instruction_index+iteration+1, 7, "");
							tablechart.setvalue(myInstruction.instruction_index+iteration+1, 6, "");
							tablechart.setvalue(myInstruction.instruction_index+iteration+1, 5, "");
							}
						}

					}//end of PC check
					else
					{
						myInstruction = new Instruction("NOP");
					}
				}//end of cache if check
				else{
					myInstruction = new Instruction("NOP");
				}
			}//end of tempPC count check
			else {
				myInstruction = new Instruction("NOP");
			}
			myInstruction.flush = false;  // valid instruction
		}

	}

	/**
	 * returns a string representation of the current instruction and the results of its processing.
	 */
	public String toString() {
		String temp;

		if (myInstruction.flush == true) {
			temp = "FLUSHED: \n" + myInstruction + "\n";
			return temp;
		}
		if ((PC >= 0) && (PC < instructionSize) )
			temp = Integer.toString(PC) + ":\n" + myInstruction + "\n";
		else
			temp = myInstruction + "\n";
		return temp;
	}

}
